<!DOCTYPE html>
<html class="Content">
<head>
    <title>xUnit.js: D8 on Windows</title>
    <link type="text/css" rel="Stylesheet" href="../Style/documentation.css" />
</head>
<body>
    <h1>D8 on Windows</h1>
    <p>
        The D8 console runner includes the ability to execute system shell commands on Posix systems. Unfortunately, this ability is absent from the Windows version
        of the D8 console runner. 
    </p>
    <p>
        To accommodate this requires some small changes to the V8 source code before building the solution on Windows.
    </p>
    <h3>Source:</h3>
    <h4 class="Indent-2">d8.cc (line 875)</h4>
    <p>
        We need to change this compiler directive to allow OS Methods to be added in Windows compilations:
    </p>
    <p>
        From:
        <span class="Code">
#if !defined(V8_SHARED) && !defined(_WIN32) && !defined(_WIN64)
        </span>
        To:
        <span class="Code">
#if !defined(V8_SHARED)
        </span>
    </p>
    <h3>Source:</h3>
    <h4 class="Indent-2">d8-windows.cc (line 29-39)</h4>
    <p>
        Now, we need to provide an implementation of the OS Shell Methods for Windows. Change the implementation of this class:
    </p>
    <p>
        From:
        <span class="Code">
#include "d8.h"
#include "d8-debug.h"
#include "debug.h"
#include "api.h"


namespace v8 {


void Shell::AddOSMethods(Handle<ObjectTemplate> os_templ) {
}
        </span>
        To:
        <span class="Code">
#include "d8.h"
#include "d8-debug.h"
#include "debug.h"
#include "api.h"
#include "string"
#include "iostream"
#include "stdio.h"

namespace v8 {


void Shell::AddOSMethods(Handle<ObjectTemplate> os_templ) {
  os_templ->Set(String::New("system"), FunctionTemplate::New(System));
}


void Shell::System(const FunctionCallbackInfo<Value>& args) {
  std::string command = "";
  for (int i = 0; i < args.Length(); i++) {
    std::string str(*v8::String::Utf8Value(args[i]));
    command += " ";
    command += str;
  }
  args.GetReturnValue().SetUndefined();
  if (!command.empty()) {
    command = "cmd.exe /C \"" + command + "\"2>&1";
    std::string result = "";
    FILE* pipe = NULL;
    pipe = _popen(command.c_str(), "r");
    if (!pipe) {
      v8::Local<v8::String> error = String::New("Error running command.");
      args.GetReturnValue().Set(ThrowException(error));
    } else {
      char buffer[128];
      while (!feof(pipe)) {
        if (fgets(buffer, 128, pipe) != NULL) {
          result += buffer;
        }
      }
      int status = _pclose(pipe);
      if (status != 0) {
        v8::Local<v8::String> output = v8::String::New(result.c_str());
        args.GetReturnValue().Set(ThrowException(output));
      } else {
        args.GetReturnValue().Set(v8::String::New(result.c_str()));
      }
    }
  }
}
        </span>
    </p>
    <p>
        If you prefer not to make these changes yourself, you can download a compiled version of the Windows d8 executable with these changes 
        already integrated from the <a href="../Guide/Console/supported-hosts.html">Supported Host Engines</a> page.
    </p>
</body>
</html>